package utils;
/**
 * TablaSimbolos
 * Descripcion: Tabla de simbolo del lenguaje fuente
 * @author PLg Group
 */
import java.util.Vector;

import utils.enumerados.ClaseTipos;
import utils.enumerados.ClaseToken;
import utils.nodos.INodoEstructura;
import utils.nodos.NodoParametros;

import AnalisisLexico.Token.Token;

public class TablaSimbolos {
	/**
     * Lexema: cadena de caracteres del codigo fuente
     */
    private Vector<String> vLexema;
    /**
     * vIdentificador: identificador del token
     */
    private Vector<Integer> vIdentificador;
    /**
     * vClase: Segun el valor de este campo, en la semantica y en la traduccion, se
     * trataran de manera diferente.
     * Posibles valores:
     *    - TIPO
     *    - VARIABLE
     *    - FUNCION
     */
    private Vector<ClaseToken> vClase;
    /**
     * Direccion que ocuparan en memoria. Hay que distinguir:
     *  Variables y funciones: El rango de direcciones iran de  0 a infinito
     *  Tipos: Siempre tendran el valor MIN_INT, ya que NO se traducen a lenguaje objeto
     */
    private Vector<Integer> vPosMemoria;
    /**
     * Hay que distinguir:
     *  -Tipo basico:
     *      - valor 0 : entero
     *      - valor 1 : real
     *      - valor 2 : booleano
     *  -Tipos complejos:
     *      - valor 3 : puntero
     *      - valor 4 : registro
     *      - valor 5 : array
     *  -Tipos contruidos:
     *      - valor 6 a infinito: Tipos declarados por el programador, este valor, restando 6
     *      sera una referecia a un valor de tipo declarado por nosotros        
     */
    private Vector<ClaseTipos> vTipo;
    /**
     * Contiene la estructura del tipo
     */
    private Vector<INodoEstructura> vEstructuras;
    /**
     * Se encarga e asignar la memoria a las variables decalradas
     */
    //private int contador;
    /**
     * 
     */
    private Vector<Integer> vNivel;
    /**
     * 
     */
    private Vector<Integer> vContador;
    
     
     public Vector<String> getVLexema(){
    	 return vLexema;
     }
     
     public Vector<Integer> getVIdentificador(){
    	 return vIdentificador;
     }
     
     public Vector<ClaseToken> getVClase(){
    	 return vClase;
     }
     
     public Vector<Integer> getVPosMemoria(){
    	 return vPosMemoria;
     }
     
     public Vector<ClaseTipos> getVTipo(){
    	 return vTipo;
     }
     
     public Vector<INodoEstructura> getVEstructuras(){
    	 return vEstructuras;
     }
     
     public Vector<Integer> getVNivel(){
    	 return vNivel;
     }
     
     public TablaSimbolos(){
    	 //contador = -1;
    	 //TABLA NUEVA
    	 vLexema =  new Vector<String>();
    	 vIdentificador = new Vector<Integer>();
    	 vPosMemoria = new Vector<Integer>();
    	 vClase = new Vector<ClaseToken>();
    	 vTipo = new Vector<ClaseTipos>();
    	 vEstructuras = new Vector<INodoEstructura>();
    	 vNivel = new Vector<Integer>();
    	 vContador = new Vector<Integer>();
    	 for(int i= 0; i< 10; i++)
    		 vContador.add(0);
     }

     public void meteToken(String s, int id, ClaseToken c, ClaseTipos t, int nivel, int instr){
    	 //TABLA NUEVA
    	 vLexema.add(s);
    	 vIdentificador.add(id);
    	 vPosMemoria.add(instr);
    	 vClase.add(c);
    	 vTipo.add(t);
    	 vNivel.add(nivel);
    	 vEstructuras.add(new NodoParametros());
    	 
     }
     public void meteToken(String s, int id, ClaseToken c, ClaseTipos t, INodoEstructura estr, int nivel){
    	 //TABLA NUEVA
    	 vLexema.add(s);
    	 vIdentificador.add(id);
    	 if(nivel > 0 && vContador.elementAt(nivel) == 0)
    		 vContador.add(nivel,2);
    	 vPosMemoria.add(vContador.elementAt(nivel));
    	 vClase.add(c);
    	 vTipo.add(t);
    	 vEstructuras.add(estr);
    	 vNivel.add(nivel);
    	 if(c == ClaseToken.VARIABLE ){
    		 int cont = vContador.elementAt(nivel)+ estr.getOffset();
    		 vContador.add(nivel,cont);
    	 }
     }
     public void estableceEstructura(String s, INodoEstructura n){
    	 int pos = vLexema.indexOf(s);
    	 vEstructuras.remove(pos);
    	 vEstructuras.insertElementAt(n, pos);//add(pos, n);
     }
     public void estableceClase(String s, ClaseToken clase){
    	 int pos = vLexema.indexOf(s);
    	 vClase.add(pos,clase);
     }
     public void esblaceTipo(String s, ClaseTipos tipo){
    	 int pos = vLexema.indexOf(s);
    	 vTipo.add(pos,tipo);
     }
     public void establecePosMem(String s, int posInstr){
    	 int pos = vLexema.indexOf(s);
    	 vPosMemoria.add(pos,posInstr);
     }
     public boolean esTipo(String s){
    	 boolean b = false;
    	 int i = vLexema.indexOf(s);
    	 if(i >= 0)
    		 if(vClase.elementAt(i)== ClaseToken.TIPO)
    			 b= true;
    	 return b;
     }
     public boolean esVariable(String s){
    	 boolean b = false;
    	 int i = vLexema.indexOf(s);
    	 if(i >= 0)
    		 if(vClase.elementAt(i)== ClaseToken.VARIABLE)
    			 b= true;
    	 return b;
     }
     public boolean esFuncion(String s){
    	 boolean b = false;
    	 int i = vLexema.indexOf(s);
    	 if(i >= 0)
    		 if(vClase.elementAt(i)== ClaseToken.FUNCION)
    			 b= true;
    	 return b;
     }
     public boolean esProcedimiento(String s){
    	 boolean b = false;
    	 int i = vLexema.indexOf(s);
    	 if(i >= 0)
    		 if(vClase.elementAt(i)== ClaseToken.PROCEDIMIENTO)
    			 b= true;
    	 return b;
     }
     public INodoEstructura dameEstructura(String s){
    	 INodoEstructura nodo = null;
    	 int i = vLexema.indexOf(s);
    	 if(i >= 0)
    		 //if(vClase.elementAt(i)== ClaseToken.TIPO)
    			 nodo = vEstructuras.elementAt(i);
    	 return nodo;
     }
     public ClaseTipos dameTipo(String s){
    	 ClaseTipos nodo = null;
    	 int i = vLexema.indexOf(s);
    	 if(i >= 0)
    		 //if(vClase.elementAt(i)== ClaseToken.TIPO)
    			 nodo = vTipo.elementAt(i);
    	 return nodo;
     }
     
     public boolean estaToken(String s){
    	 return vLexema.contains(s);
     }
     public int dirMemoriaToken(Token t){
    	 return vPosMemoria.elementAt( vLexema.indexOf(t.getLexema()));
     }
     public int nivel(String l){
    	 int n = 0;
    	 n = vNivel.elementAt(vLexema.indexOf(l));
    	 return n;
     }
     public int numReservaVar(int nivel){
    	 return vContador.elementAt(nivel);
     }
     public int nivelMax(){
    	 int max = Integer.MIN_VALUE;
    	 for(int i = 0; i < vNivel.size();i++)
    		 if(max < vNivel.elementAt(i))
    			 max = vNivel.elementAt(i);
    	return max+1;
     }
     public void muestraContenido(){
    	 for(int i = 0; i < vLexema.size();i++){
    		System.out.print(vLexema.elementAt(i)+"    ");
    		System.out.print(vIdentificador.elementAt(i)+"   ");
    		System.out.print(vClase.elementAt(i).toString()+"   ");
    		if(vTipo.elementAt(i) != null)
    			System.out.print(vTipo.elementAt(i).toString()+"    ");
    		System.out.print(vPosMemoria.elementAt(i)+"    ");
    		System.out.println(vNivel.elementAt(i)+"    ");
    	 }
     }

}
